package com.yungu.swift.api.base.filter;

import com.fasterxml.jackson.databind.JsonNode;
import com.yungu.swift.api.config.ApplicationConfig;
import com.yungu.swift.api.utils.RsaUtil;
import com.yungu.swift.base.ResponseData;
import com.yungu.swift.constants.MagicConstant;
import com.yungu.swift.utils.JsonUtils;
import com.yungu.swift.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.Iterator;
import java.util.Map;

import static com.yungu.swift.api.base.ApiErrorEnum.DECRYPT_ERROR;

/**
 * @author Zerrion
 * @version 1.0
 * @description 对前端请求进行解密的 Filter
 * @date 2018/11/9 20:12
 */
@Slf4j
@WebFilter(urlPatterns = {"/api/*", "/h5/*"})
public class DecryptFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        if (!ApplicationConfig.SERVER_CONFIG.getSafety().getEncrypt()) {
            //请求是JSON格式数据
            if (null != request.getContentType() && request.getContentType().contains(MagicConstant.PARAMS_JSON)) {
                BodyRequestWrapper bodyRequestWrapper = new BodyRequestWrapper(request);
                filterChain.doFilter(bodyRequestWrapper, response);
            } else {
                filterChain.doFilter(request, response);
            }
        } else {
            //请求是JSON格式数据
            if (null != request.getContentType() && request.getContentType().contains(MagicConstant.PARAMS_JSON)) {
                try {
                    BodyRequestWrapper bodyRequestWrapper = new BodyRequestWrapper(request);
                    String bodyStr = getBodyString(bodyRequestWrapper.getReader());
                    log.info("解密前请求内容：{}", bodyStr);
                    JsonNode jsonNode = JsonUtils.readNode(bodyStr);
                    if (jsonNode.has(MagicConstant.PARAMS_ENCRYPTION)) {
                        //先进行url解码
                        String urlDecryptStr = URLDecoder.decode(jsonNode.get("encryption").asText(), "UTF-8");
                        //进行RSA解码
                        String decryptStr = RsaUtil.decryptByPrivate(urlDecryptStr, RsaUtil.SERVER_PRIVATE_KEY);
                        bodyRequestWrapper.setBody(decryptStr);
                    }
                    filterChain.doFilter(bodyRequestWrapper, response);
                } catch (Exception e) {
                    log.error("数据解密异常", e);
                    response.getWriter().print(JsonUtils.writeJsonStr(ResponseData.buildErrorResponse(DECRYPT_ERROR.getCode(), DECRYPT_ERROR.getMsg())));
                }
            } else {
                //这边不对上传文件接口加密
                String strUri = request.getRequestURI();
                log.info("-------------------------------strUri:" + strUri);
                if (strUri.contains("/yue/share") || strUri.contains("/h5") || strUri.contains("/qrCodeView")
                        || strUri.contains("/pay/wx/callback") || strUri.contains("/pay/alipay/callback")
                        || strUri.contains("/img/") || strUri.contains("/css/") || strUri.contains("/share/")
                        || strUri.contains("/js/") || strUri.contains("/admin/") || strUri.contains("/plugin/")
                        || strUri.contains("/giftCollection") || strUri.contains("/driver_passenger")
                        || strUri.contains("/invite/driver") || strUri.contains("/token/share/info")
                        || strUri.contains("/drawQrCodeGift") || strUri.contains("/uploadImage")
                        || strUri.contains("/upload") || strUri.contains("/api/v1/upload/image")) {
                    filterChain.doFilter(request, response);
                    return;
                }
                //获取加密的参数串
                String paramStr = request.getParameter("params");
                if (StringUtils.isNotEmpty(paramStr)) {
                    try {
                        //先进行url解码
                        String urlDecryptStr = URLDecoder.decode(paramStr, "UTF-8");
                        //进行RSA解码
                        String decryptStr = RsaUtil.decryptByPrivate(urlDecryptStr, RsaUtil.SERVER_PRIVATE_KEY);
                        //获取参数，拼接到请求中
                        ParameterRequestWrapper parameterRequestWrapper = new ParameterRequestWrapper(request);
                        JsonNode jsonNode = JsonUtils.readNode(decryptStr);
                        Iterator<Map.Entry<String, JsonNode>> jsonNodes = jsonNode.fields();
                        while (jsonNodes.hasNext()) {
                            Map.Entry<String, JsonNode> node = jsonNodes.next();
                            parameterRequestWrapper.addParameter(node.getKey(), node.getValue().asText());
                        }
                        filterChain.doFilter(parameterRequestWrapper, response);
                    } catch (Exception e) {
                        log.error("数据解密异常", e);
                        response.getWriter().print(JsonUtils.writeJsonStr(ResponseData.buildErrorResponse(DECRYPT_ERROR.getCode(), DECRYPT_ERROR.getMsg())));
                    }
                } else {
                    filterChain.doFilter(request, response);
                }
            }
        }
    }

    private static String getBodyString(BufferedReader br) throws IOException {
        StringBuffer buffer = new StringBuffer();
        String line;
        while ((line = br.readLine()) != null) {
            buffer.append(line);
        }
        br.close();
        return buffer.toString();
    }
}
